package com.price.common.util

import android.text.TextUtils
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonParseException
import com.google.gson.JsonParser
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import com.google.gson.reflect.TypeToken
import com.price.common.extend.doCustomCrashListener
import java.lang.reflect.Type


object JsonUtils {
    private var gson: Gson? = null

    /**
     * json字符串转对象，解析失败，不会抛出异常，会直接返回null
     *
     * @param json json字符串
     * @param type 对象类类型
     * @param <T>  返回类型
     * @return T，返回对象有可能为空
    </T> */
    fun <T> fromJson(json: String, type: Class<T>): T? {
        return try {
            val gson = buildGson()
            return gson!!.fromJson(json, type)
        } catch (ignore: Exception) {
            doCustomCrashListener?.onCrash(ignore)
            null
        }
    }
    fun <T> fromJson(json: String, type: Type): T? {
        return try {
            val gson = buildGson()
            return gson!!.fromJson(json, type)
        } catch (ignore: Exception) {
            doCustomCrashListener?.onCrash(ignore)
            null
        }
    }

    inline fun <reified T> fromJson(json: String): T? {
        val type= object :TypeToken<T>(){}.type
        return fromJson(json,type)
    }

    fun toJson(`object`: Any?): String {
        return buildGson()!!.toJson(`object`)
    }

    /**
     * 转成list
     * 解决泛型问题
     * @param json
     * @param cls
     * @param <T>
     * @return
    </T> */
    inline fun <reified T> jsonToList(json: String?): List<T>? {
        val typeToken = object : TypeToken<List<T>>() {}.type
        val gson = buildGson()
        return gson?.fromJson<List<T>>(json, typeToken)
    }


    /**
     * 转成list中有map的
     * @param gsonString
     * @return
     */
    inline fun <reified K, reified V> jsonToListMaps(gsonString: String?): List<Map<K, V>?>? {
        val gson = buildGson()
        return gson?.fromJson(
                gsonString,
                object : TypeToken<List<Map<K, V>>?>() {}.type
            )
    }

    /**
     * 转成map的
     *
     * @param gsonString
     * @return
     */
    inline fun <reified K, reified V> jsonToMaps(gsonString: String?): Map<K, V>? {
        val gson = buildGson()
        return gson?.fromJson(gsonString, object : TypeToken<Map<String, V>?>() {}.type)
    }

    // -------

    /**
     * 按章节点得到相应的内容
     * @param jsonString json字符串
     * @param note 节点
     * @return 节点对应的内容
     */
    fun getNoteJsonString(jsonString: String?, note: String?): String ?{
        return try {
            if (TextUtils.isEmpty(jsonString)) {
                throw RuntimeException("json字符串")
            }
            if (TextUtils.isEmpty(note)) {
                throw RuntimeException("note标签不能为空")
            }
            val element = JsonParser().parse(jsonString)
            if (element.isJsonNull) {
                throw RuntimeException("得到的jsonElement对象为空")
            }
            return element.asJsonObject[note].toString()
        }catch (e:Exception){
            doCustomCrashListener?.onCrash(e)
            null
        }
    }



    fun buildGson(): Gson? {
        if (gson == null) {
            gson = GsonBuilder().disableHtmlEscaping().registerTypeAdapter(
                String::class.java, StringAdapter()
            ).registerTypeAdapter(Int::class.javaPrimitiveType, IntegerDefault0Adapter())
                .registerTypeAdapter(
                    Int::class.java, IntegerDefault0Adapter()
                ).registerTypeAdapter(Double::class.javaPrimitiveType, DoubleDefault0Adapter())
                .registerTypeAdapter(
                    Double::class.java, DoubleDefault0Adapter()
                ).registerTypeAdapter(Long::class.javaPrimitiveType, LongDefault0Adapter())
                .registerTypeAdapter(
                    Long::class.java, LongDefault0Adapter()
                ).create()
        }
        return gson
    }


    private class StringAdapter : JsonSerializer<String?>,
        JsonDeserializer<String?> {
        @Throws(JsonParseException::class)
        override fun deserialize(
            json: JsonElement,
            typeOfT: Type,
            context: JsonDeserializationContext
        ): String {
            return if (json is JsonPrimitive) {
                json.getAsString()
            } else {
                json.toString()
            }
        }

        override fun serialize(
            src: String?,
            typeOfSrc: Type,
            context: JsonSerializationContext
        ): JsonElement {
            return JsonPrimitive(src)
        }
    }

    private class IntegerDefault0Adapter : JsonSerializer<Int?>,
        JsonDeserializer<Int?> {
        @Throws(JsonParseException::class)
        override fun deserialize(
            json: JsonElement,
            typeOfT: Type,
            context: JsonDeserializationContext
        ): Int {
            try {
                val str = json.asString
                if ("" == str || "null" == str) { //定义为int类型,如果后台返回""或者null,则返回0
                    return 0
                }
            } catch (ignore: Exception) {
            }
            return json.asInt
        }

        override fun serialize(
            src: Int?,
            typeOfSrc: Type,
            context: JsonSerializationContext
        ): JsonElement {
            return JsonPrimitive(src)
        }
    }

    private class DoubleDefault0Adapter : JsonSerializer<Double?>,
        JsonDeserializer<Double?> {
        @Throws(JsonParseException::class)
        override fun deserialize(
            json: JsonElement,
            typeOfT: Type,
            context: JsonDeserializationContext
        ): Double {
            try {
                val str = json.asString
                if ("" == str || "null" == str) { //定义为double类型,如果后台返回""或者null,则返回0.00
                    return 0.00
                }
            } catch (ignore: Exception) {
            }
            return json.asDouble
        }

        override fun serialize(
            src: Double?,
            typeOfSrc: Type,
            context: JsonSerializationContext
        ): JsonElement {
            return JsonPrimitive(src)
        }
    }

    private class LongDefault0Adapter : JsonSerializer<Long?>,
        JsonDeserializer<Long?> {
        @Throws(JsonParseException::class)
        override fun deserialize(
            json: JsonElement,
            typeOfT: Type,
            context: JsonDeserializationContext
        ): Long {
            try {
                val str = json.asString
                if ("" == str || "null" == str) { //定义为long类型,如果后台返回""或者null,则返回0
                    return 0L
                }
            } catch (ignore: Exception) {
            }
            return json.asLong
        }

        override fun serialize(
            src: Long?,
            typeOfSrc: Type,
            context: JsonSerializationContext
        ): JsonElement {
            return JsonPrimitive(src)
        }
    }
}